package com.web.kdl.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.web.kdl.config.security.SecurityConstants;
import com.web.kdl.pojo.model.LoginUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * @Author： shulibin
 * @Date： 2025/7/25 13:44
 * @Describe：
 */
@Component
public class JwtTokenUtil {
    // 密钥
    private static String secret;
    @Value("${kdl-system.auth.jwt.secret:aBcD1234eFgH5678IjKl90MnOpQrStUvWxYz4567}")
    public void setSecret(String secret){
        JwtTokenUtil.secret = secret;
    }

    // token过期时间
    private static Long expiration;
    @Value("${kdl-system.auth.jwt.expiration}")
    public void setExpiration(Long expiration) {
        JwtTokenUtil.expiration = expiration;
    }

    // 设置JWT的生效时间 该时间之前都不生效
    private static String notBefore;
    @Value("${kdl-system.auth.jwt.not-before}")
    public void setNotBefore(String notBefore){
        JwtTokenUtil.notBefore = notBefore;
    }
    /**
     * 生成token
     * @param userId;
     * @return jwt-token
     */
    public static String generateToken( String userId) {
        Map<String, Object> claimsMap = new HashMap<>();
        claimsMap.put(SecurityConstants.USER_KEY, userId);
        return Jwts.builder()
                .setClaims(claimsMap)
                .setId(UUID.randomUUID().toString(true))
                .setNotBefore(notBeforeDate())
                .setIssuedAt(nowDate())
                .signWith(signKey())
                .compact();
    }


    public static boolean validateToken(String token, String userId) {
        if(StrUtil.isBlank(userId)){
            return false;
        }
        final String claimUserId = extractUserId(token);
        return userId.equals(claimUserId);
    }

    private static SecretKey signKey(){
        return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
    }
    /**
     * 解析token字符串中的加密信息, 提取所有声明的方法
     * @param token jwt-token
     * @return Claims
     */
    private static Claims extractAllClaims(String token){
        return Jwts
                .parserBuilder()
                .setSigningKey(signKey())
                .build()
                .parseClaimsJws(token)
                .getBody();
    }
    /**
     * 从token中提取特定声明
     */
    private static  <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token);
        return claimsResolver.apply(claims);
    }
    /**
     * 从token中提取用户ID
     */
    public static String extractUserId(String token) {
        return extractClaim(token, Claims -> Claims.get(SecurityConstants.USER_KEY, String.class));
    }

    private static Date extractExpiration(String token) {
        return extractClaim(token, Claims::getExpiration);
    }

    private static boolean isTokenExpired(String token) {
        return extractExpiration(token).before(new Date());
    }

    private static Date expirationDate() {
        return new Date(System.currentTimeMillis() + expiration * 1000);
    }

    private static Date nowDate() {
        return new Date(System.currentTimeMillis());
    }

    private static Date notBeforeDate() {
        return DateUtil.parse(notBefore,"yyyy-MM-dd");
    }
}
